package cn.dong.order.controller.api;

import cn.dong.api.domain.CommonResult;
import cn.dong.api.domain.ResultCodeEnum;
import cn.dong.base.handler.CustomException;
import cn.dong.order.domain.TradeOrder;
import cn.dong.order.feign.CourseService;
import cn.dong.order.service.TradeOrderService;
import cn.dong.order.service.TradePayLogService;
import cn.dong.order.service.WxPayService;
import cn.dong.order.utils.IpUtils;
import cn.dong.order.utils.StreamUtils;
import cn.dong.order.utils.WxPayProperties;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import github.wxpay.sdk.WXPayUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/api/order/trade-order")
@Slf4j
public class WxPayController {

    @Autowired
    private WxPayService wxPayService;

    @Autowired
    private TradeOrderService tradeOrderService;

    @Autowired
    private WxPayProperties wxPayProperties;

    @Autowired
    private TradePayLogService tradePayLogService;

    @Autowired
    private CourseService courseService;

    /**
     * 生成二维码，获取订单信息
     *
     * @return
     */
    @GetMapping("/auth/getQrCode/{orderNo}")
    public CommonResult getQrCodeUrl(@PathVariable String orderNo, HttpServletRequest request) {
        String addr = IpUtils.getIpAddr(request);
        Map map = wxPayService.getQrcodeUrl(orderNo, addr);
        return CommonResult.ok().data(map);
    }

    /**
     * 支付订单的回调方法
     *
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("/callback/notify")
    public String callbackNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 获取微信响应
        ServletInputStream stream = request.getInputStream();
        String params = StreamUtils.inputStream2String(stream, "UTF-8");
        Map<String, String> map = WXPayUtil.xmlToMap(params);

        if ("SUCCESS".equals(map.get("return_code"))) {
            // 检验签名
            if (WXPayUtil.isSignatureValid(params, wxPayProperties.getPartnerKey())) {
                // 获取金额
                String money = map.get("total_fee");
                String outTradeNo = map.get("out_trade_no");
                QueryWrapper<TradeOrder> wrapper = new QueryWrapper<>();
                wrapper.eq("order_no", outTradeNo);
                TradeOrder order = tradeOrderService.getOne(wrapper);
                // 校验金额
                if (order != null &&
                        order.getTotalFee().multiply(new BigDecimal(100)).intValue() == Integer.parseInt(money)) {
                    // 微信频繁发送信息，如何解决幂等性，保证结果的一致性
                    if (order.getStatus() != 1) {
                        // 改变订单状态
                        tradeOrderService.updateState(order);
                        // 增加支付日志信息，增加到表中
                        tradePayLogService.saveOrderLog(map);
                        // 增加订单销量
                        courseService.updateBuyCount(order.getId());
                    }

                    //支付成功：给微信发送我已接收通知的响应
                    //创建响应对象
                    Map<String, String> returnMap = new HashMap<>();
                    returnMap.put("return_code", "SUCCESS");
                    returnMap.put("return_msg", "OK");
                    String returnXml = WXPayUtil.mapToXml(returnMap);
                    response.setContentType("text/xml");
                    log.info("支付成功，通知已处理");
                    return returnXml;
                }
            }
        }
        // 参数数据不一致，接收微信信息失败
        Map<String, String> returnMap = new HashMap<>(3);
        returnMap.put("return_code", "FAIL");
        returnMap.put("return_msg", "");
        response.setContentType("text/xml");
        log.info("校验失败");
        return WXPayUtil.mapToXml(returnMap);
    }


    /**
     * 查询订单状态
     * @param id
     * @return
     */
    @GetMapping("/auth/findStatus/{id}")
    public CommonResult findStatus(@PathVariable("id") String id){
        boolean result = tradeOrderService.findStatus(id);
        if (result) {
            // 订单支付
            return CommonResult.ok().message("支付成功！").data(true);
        }
        // 未支付
        throw new CustomException(ResultCodeEnum.PAY_RUN);
    }


}
